package no.uib.kwikktaim.gui;

import java.awt.*;
import java.awt.event.WindowEvent;
import java.awt.event.WindowListener;
import java.net.URL;

import javax.swing.*;
import javax.swing.border.Border;

import no.uib.kwikktaim.core.FrameHandler;
import no.uib.kwikktaim.core.SaveInfoToFile;
import no.uib.kwikktaim.core.SerializingBean;
import no.uib.kwikktaim.core.TimeChecker;
import no.uib.kwikktaim.gui.actionlisteners.ChangeTrack;
import no.uib.kwikktaim.gui.actionlisteners.KeyFramesListener;
import no.uib.kwikktaim.gui.actionlisteners.ListManipulationListener;
import no.uib.kwikktaim.gui.actionlisteners.ManipulateMenu;
import no.uib.kwikktaim.gui.actionlisteners.MinimizeMaximizePlaylist;
import no.uib.kwikktaim.gui.actionlisteners.OpenFile;
import no.uib.kwikktaim.gui.actionlisteners.PlayPause;
import no.uib.kwikktaim.gui.actionlisteners.SliderEvent;
import no.uib.kwikktaim.gui.actionlisteners.TimeSliderChange;
import no.uib.kwikktaim.gui.actionlisteners.VolumeChanger;
import no.uib.kwikktaim.utils.PlayerOptions;

/**
 * Kwikktaims main window. Most of the GUI is here
 */
public class MainWindow extends JFrame implements WindowListener {

	private PlayerOptions playpause = PlayerOptions.PAUSE;
	public int currentlyPlaying=0;

	//Icons for buttons
	public  Icon iconPlay;
	public  Icon iconPause;
	private Icon iconStop;
	private Icon iconAdd;
	private Icon iconPrev;
	private Icon iconNext;
	private Icon iconMute;
	private Icon iconFullVolume;
	private Icon iconKeyFrame;
	JPanel panelPlayer;

	// Window components
	private JButton buttonPlay;

	//Assorted buttons
	private JButton buttonStop;
	public JButton buttonAdd;
	private JButton buttonNext;
	private JButton buttonPrevious;
	private JButton buttonMute;
	private JButton buttonKeyFrame;

	// The keyframe window
	public KeyFrames kf;

	public JButton buttonPlaylistMinimize;

	public JSlider sliderTime; //This slider shows time
	public JSlider sliderVolume; //And this volume

	public JScrollPane listScroller;

	private JPanel panelControls; // Container for controls
	private JPanel panelPlayList; // Container for playlist
	private JPanel panelPlayListControls; // Container for playlist controls
	private JPanel panelTimeKey; // Container for time and keyframebutton


	public JList listPlayList;
	public DefaultListModel model;
	private MediaViewer player;

	public SerializingBean saved;

	public MediaViewer getPlayer() {
		return player;
	}


	public void setPlayer(MediaViewer player) {
		this.player = player;
		panelPlayer.add(player,BorderLayout.CENTER);
		this.setSize(this.getSize().width, this.getSize().width-1);
		this.setSize(this.getSize().width, this.getSize().width+1);
	}


	private PlayPause ppause = new PlayPause(this);
	private TimeChecker tc;

	public MainWindow() {
		super("KwikkTaim"); // Window title
		initialize();
		setup();
		tc = new TimeChecker(this);
		new Thread(tc).start();
	}
	/**
	 * Initialize GUI components
	 */
	private void initialize() {
		// Standard dimension for buttons!
		Dimension dimToolbar = new Dimension(30,30);

		// Load icons
		iconPause  = new javax.swing.ImageIcon(getClass().getResource("/no/uib/kwikktaim/img/media-playback-start.png"));
		iconPlay = new javax.swing.ImageIcon(getClass().getResource("/no/uib/kwikktaim/img/media-playback-pause.png"));
		iconStop = new javax.swing.ImageIcon(getClass().getResource("/no/uib/kwikktaim/img/media-playback-stop.png"));
		iconAdd = new javax.swing.ImageIcon(getClass().getResource("/no/uib/kwikktaim/img/media-eject.png"));
		iconPrev = new javax.swing.ImageIcon(getClass().getResource("/no/uib/kwikktaim/img/media-skip-backward.png"));
		iconNext = new javax.swing.ImageIcon(getClass().getResource("/no/uib/kwikktaim/img/media-skip-forward.png"));
		iconMute = new javax.swing.ImageIcon(getClass().getResource("/no/uib/kwikktaim/img/audio-volume-muted.png"));
		iconFullVolume = new javax.swing.ImageIcon(getClass().getResource("/no/uib/kwikktaim/img/audio-volume-high.png"));
		iconKeyFrame = new javax.swing.ImageIcon(getClass().getResource("/no/uib/kwikktaim/img/keyframe.png"));


		// Create play controls
		buttonPlay = new JButton();
		buttonStop = new JButton();
		buttonAdd = new JButton();
		buttonNext = new JButton();
		buttonPrevious = new JButton();
		buttonMute = new JButton();
		buttonKeyFrame = new JButton();

		// Playlist controls
		Dimension dim = new Dimension(16,16);
		Border border = BorderFactory.createEmptyBorder(5, 0, 0, 0);
		buttonPlaylistMinimize = new JButton("Hide Playlist");
		panelPlayListControls = new JPanel();
		buttonPlaylistMinimize.setPreferredSize(dim);
		buttonPlaylistMinimize.setBorder(border);


		// Set sizes
		buttonPlay.setPreferredSize(dimToolbar);
		buttonStop.setPreferredSize(dimToolbar);
		buttonAdd.setPreferredSize(dimToolbar);
		buttonNext.setPreferredSize(dimToolbar);
		buttonPrevious.setPreferredSize(dimToolbar);
		buttonMute.setPreferredSize(dimToolbar);
		buttonKeyFrame.setPreferredSize(new Dimension(25,25));

		//Panels
		panelPlayer = new JPanel(new BorderLayout());
		panelTimeKey = new JPanel(new BorderLayout());

		//Retrieve and set info for the saving-bean
		saved = SaveInfoToFile.loadFromFile("settings.dat");

		if(saved==null) {
			saved = new SerializingBean();
		}

		sliderTime = new JSlider(0,100);
		sliderVolume = new JSlider(0,100);
		sliderVolume.setPreferredSize(new Dimension((int)dimToolbar.getWidth()*3,(int)dimToolbar.getHeight()));

		player = new MediaViewer(this);

		panelControls = new JPanel(new FlowLayout());
		model = saved.getPlaylist();

	}

	/**
	 * Connecting and setting up menyes, adding actionlisteners etc.
	 */
	private void setup() {

		// Add icons to controls
		buttonPlay.setIcon(iconPause);
		buttonStop.setIcon(iconStop);
		buttonAdd.setIcon(iconAdd);
		buttonNext.setIcon(iconPrev);
		buttonPrevious.setIcon(iconNext);
		buttonMute.setIcon(iconFullVolume);
		buttonKeyFrame.setIcon(iconKeyFrame);

		// Time starts at 0.
		sliderTime.setValue(0);

		//Fetching the JMenuBar from the MenuFactory
		JMenuBar menuBar = MenuFactory.getMenu();
		this.setJMenuBar(menuBar);

		// Set up the playlist
		panelPlayList = new JPanel();
		panelPlayList.setLayout(new BoxLayout(panelPlayList,
				BoxLayout.PAGE_AXIS));
		listPlayList = new JList(model);
		listPlayList.setCellRenderer(new MediaListRenderer());

		listScroller = new JScrollPane(listPlayList);
		listScroller.setPreferredSize(new Dimension(250, 80));
		listScroller.setAlignmentX(LEFT_ALIGNMENT);

		// Layout for main window
		this.setLayout(new BorderLayout());

		// Add controls to GUI
		panelControls.add(buttonPlay);
		panelControls.add(buttonStop);
		panelControls.add(buttonAdd);
		panelControls.add(buttonNext);
		panelControls.add(buttonPrevious);
		panelControls.add(buttonMute);
		panelControls.add(sliderVolume);

		// Add playlist controls
		panelPlayListControls.setLayout(new BorderLayout());
		panelPlayListControls.add(buttonPlaylistMinimize, BorderLayout.CENTER);


		// Add scrollbar to the playlist & other stuff
		panelPlayList.setLayout(new BorderLayout());
		panelPlayList.add(listScroller, BorderLayout.CENTER);
		panelPlayList.add(panelPlayListControls,BorderLayout.SOUTH);

		// Player and the time slide
		panelPlayer.add(player, BorderLayout.CENTER);

		panelTimeKey.add(sliderTime, BorderLayout.CENTER);
		panelTimeKey.add(buttonKeyFrame, BorderLayout.EAST);

		panelPlayer.add(panelTimeKey, BorderLayout.SOUTH);

		// Add controls to frame
		this.add(panelControls, BorderLayout.NORTH);
		this.add(panelPlayer, BorderLayout.CENTER);
		this.add(panelPlayList, BorderLayout.SOUTH);

		// Add action listeners for menu items
		menuBar.getMenu(0).getItem(0).addActionListener(new ManipulateMenu(this));

		menuBar.getMenu(1).getItem(0).addActionListener(new ManipulateMenu(this));
		menuBar.getMenu(1).getItem(1).addActionListener(new ManipulateMenu(this));
		menuBar.getMenu(1).getItem(3).addActionListener(new ManipulateMenu(this)); // Increase speed
		menuBar.getMenu(1).getItem(4).addActionListener(new ManipulateMenu(this)); // Default speed
		menuBar.getMenu(1).getItem(5).addActionListener(new ManipulateMenu(this)); // Decrease speed

		menuBar.getMenu(2).getItem(0).addActionListener(new ManipulateMenu(this));
		menuBar.getMenu(2).getItem(1).addActionListener(new ManipulateMenu(this));
		menuBar.getMenu(2).getItem(2).addActionListener(new ManipulateMenu(this));
		//TODO - implement sorting
//		menuBar.getMenu(2).getItem(3).addActionListener(new ManipulateMenu(this));
		menuBar.getMenu(3).getItem(0).addActionListener(new ManipulateMenu(this));

		sliderTime.addMouseListener(new SliderEvent(this));
		sliderTime.addChangeListener(new TimeSliderChange(this));
		buttonPlay.addActionListener(ppause);
		buttonStop.addActionListener(ppause);
		buttonMute.addActionListener(new VolumeChanger(this));
		sliderVolume.addChangeListener(new VolumeChanger(this));
		buttonAdd.addActionListener(new OpenFile(this));
		buttonNext.addActionListener(new ChangeTrack(this));
		buttonPrevious.addActionListener(new ChangeTrack(this));
		this.addWindowListener(this);
		buttonKeyFrame.addActionListener(new KeyFramesListener(this));
		ListManipulationListener lmp = new ListManipulationListener(this);
		listPlayList.addMouseListener(lmp);
		listPlayList.addKeyListener(lmp);
		buttonPlaylistMinimize.addActionListener(new MinimizeMaximizePlaylist(this));

		// Some explanation for the user
		buttonKeyFrame.setToolTipText("Show keyframes");
		buttonAdd.setToolTipText("Add a file to the playlist");
		buttonMute.setToolTipText("Mute/unmute");
		buttonNext.setToolTipText("Next song in playlist");
		buttonPrevious.setToolTipText("Previous song in playlist");
		buttonPlay.setToolTipText("Play/Pause song");
		buttonStop.setToolTipText("Stop current song");


		this.setDefaultCloseOperation(EXIT_ON_CLOSE);

		sliderVolume.setValue(saved.getVolum());

		this.pack();
		FrameHandler.centerScreen(this);
		this.setVisible(true);


	}

	public JSlider getSliderVolume() {
		return sliderVolume;
	}

	/**
	 * Load the selected file and start playing
	 */
	public void loadAndPlay() {

		if(kf != null) {
			kf.setVisible(false);
			kf.dispose();
			kf = null;
		}


		player.play((URL)listPlayList.getSelectedValue());
		sliderTime.setMaximum(getTotalTime() + 1);
		ppause.setPressedPause(false);
		currentlyPlaying = listPlayList.getSelectedIndex();
		this.setPlaypause(playpause.PLAY);
	}

	/**
	 * Continue playing (after pause)
	 */
	public void play() {

		player.play();
	}

	/**
	 * Stop the media
	 */
	public void stop() {
		player.stop();
	}

	/**
	 * Adds a media file to the playlist
	 * @param url the item that should be added
	 */
	public void addMediaToPlayList(URL url){
		model.addElement(url);
	}

	/**
	 * Adds a media file to the playlist
	 * @param url the item that should be added
	 */
	public void removeMediaFromPlayList(){
		if(listPlayList.getSelectedIndex()!= -1)
		model.remove(listPlayList.getSelectedIndex());
	}

	/**
	 * Sets play or pause-mode.
	 * @param playpause
	 */
	public void setPlaypause(PlayerOptions playpause) {
		this.playpause = playpause;
		if(playpause == PlayerOptions.PLAY) {
			buttonPlay.setIcon(iconPlay);
			player.play();
		}
		else {
			player.pause();
			buttonPlay.setIcon(iconPause);
		}
	}

	/**
	 * Getter for cheching what play-mode we are in.
	 * @return
	 */
	public PlayerOptions getPlaypause() {
		return playpause;
	}

	/**
	 * Sets the position to the time slider
	 * @param value the time
	 */
	public void setTimeSlider(int value) {
		sliderTime.setValue(value);
	}

	/**
	 * Get where we are in the media
	 * @return the time
	 */
	public int getTime() {
		if(player==null)
			return 0;
		return (int) player.getTime();
	}

	/**
	 * Gets the current time played
	 * @param time
	 */
	public void setTime(double time) {
		player.setTime(time);
	}

	/**
	 * Gets the total time of a media file.
	 * @return
	 */
	public int getTotalTime() {
		if(player==null)
			return 0;
		return player.getTotalTime();
	}

	public void setButtonStop(JButton buttonStop) {
		this.buttonStop = buttonStop;
	}

	public JButton getButtonPrevious() {
		return buttonPrevious;
	}

	public void setButtonPrevious(JButton buttonPrevious) {
		this.buttonPrevious = buttonPrevious;
	}

	public Icon getIconMute() {
		return iconMute;
	}
	public void setIconMute(Icon iconMute) {
		this.iconMute = iconMute;
	}
	public Icon getIconFullVolume() {
		return iconFullVolume;
	}
	public void setIconFullVolume(Icon iconFullVolume) {
		this.iconFullVolume = iconFullVolume;
	}
	public JButton getButtonStop() {
		return buttonStop;
	}

	public JButton getButtonMute() {
		return buttonMute;
	}
	public void setButtonMute(JButton buttonMute) {
		this.buttonMute = buttonMute;
	}

	public void dispose() {

	}

	/**
	 * Listener which saves info when we close the window
	 */
	public void windowClosing(WindowEvent e) {
		saved.setPlaylist(model);
		saved.setVolum(sliderVolume.getValue());
		if(SaveInfoToFile.saveToFile(saved,"settings.dat")) System.out.println("Lagrer info");
	}
	public void windowActivated(WindowEvent e) {}
	public void windowClosed(WindowEvent e) {}
	public void windowDeactivated(WindowEvent e) {}
	public void windowDeiconified(WindowEvent e) {}
	public void windowIconified(WindowEvent e) {}
	public void windowOpened(WindowEvent e) {}

}
